#include "precomp.h"
#include <Windows.h>
#include <filesystem>
#include <fstream>
#include <iostream>

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL, // handle to DLL module
    DWORD fdwReason,        // reason for calling function
    LPVOID /*lpReserved*/   // reserved
)
{
    switch (fdwReason)
    {
    // Initialize once for each new process.
    // Return FALSE to fail DLL load.
    case DLL_PROCESS_ATTACH:
        {
            constexpr const char* stepOutputExtension = ".step_output.txt";
            constexpr const char* stepOutputExpectedContent = "dll linked";

            char moduleFileName[MAX_PATH];
            if (GetModuleFileName(hinstDLL, moduleFileName, sizeof(moduleFileName)) == 0)
            {
                std::cerr << "Couldn't retrieve the DLL full path" << std::endl;
                return FALSE;
            }

            std::filesystem::path moduleFilePath(moduleFileName);
            moduleFilePath.replace_extension(stepOutputExtension);
            if (!std::filesystem::exists(moduleFilePath))
            {
                std::cerr << "Couldn't find the file generated by the postbuild step: '" << moduleFilePath.string() << "'" << std::endl;
                return FALSE;
            }

            std::ifstream fileStream(moduleFilePath);
            if (!fileStream.good())
            {
                std::cerr << "Couldn't read the file generated by the postbuild step: '" << moduleFilePath.string() << "'" << std::endl;
                return FALSE;
            }

            fileStream.seekg(0, fileStream.end);
            const std::streampos length = fileStream.tellg();
            fileStream.seekg(0, fileStream.beg);

            std::string content;
            content.resize(length);
            fileStream.read(content.data(), length);
            if (content.find(stepOutputExpectedContent) == std::string::npos)
            {
                std::cerr << "Content of the file generated by the postbuild step: '" << moduleFilePath.string() << "' did not contain the expected string." << std::endl;
                std::cerr << "Found '" << content << "'" << std::endl;
                std::cerr << "Expected '" << stepOutputExpectedContent << "'" << std::endl;

                return FALSE;
            }
        }
        break;

    // Do thread-specific initialization.
    case DLL_THREAD_ATTACH:
        break;

    // Do thread-specific cleanup.
    case DLL_THREAD_DETACH:
        break;

    // Perform any necessary cleanup.
    case DLL_PROCESS_DETACH:
        break;
    }

    return TRUE;
}
